package org.example.thread.aba;

import sun.awt.windows.ThemeReader;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

public class ABADemo {
    private static AtomicReference<Integer> atomicReference=new AtomicReference(100);
    //带有版本号的引用
    private static AtomicStampedReference<Integer> stampedReference=new AtomicStampedReference<>(100,1);

    public static void main(String[] args) {

        System.out.println("===以下是ABA问题的产生===");
        new Thread(()-> {
            atomicReference.compareAndSet(100,101);
            atomicReference.compareAndSet(101,100);
        },"t1").start();

        new Thread(()->{
            //先暂停一秒，保证完成ABA
            try{
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName()+"\t"+atomicReference.compareAndSet(100,2000)+"\t"+atomicReference.get());
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        },"t2").start();
        System.out.println("===以下是ABA问题的解决===");
        new Thread(()->{
            //首先获取版本号
            int stamp=stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t 第一次版本号是"+stamp
                    +"\t"+stampedReference.getReference());

            try{
                TimeUnit.SECONDS.sleep(1);
                System.out.println(atomicReference.compareAndSet(100,2000)+"\t"+atomicReference.get());
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            stampedReference.compareAndSet(100,101,stampedReference.getStamp(),
                    stampedReference.getStamp()+1);

            System.out.println(Thread.currentThread().getName()+"\t 第2次版本号是"+stamp
                    +"\t"+stampedReference.getReference());

            stampedReference.compareAndSet(101,100,stampedReference.getStamp(),
                    stampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t 第3次版本号是"+stamp
                    +"\t"+stampedReference.getReference());
        },"t3").start();

        new Thread(()->{
            int stamp=stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t 第一次版本号是"+stamp
                    +"\t"+stampedReference.getReference());
            //保证线程3完成一次ABA操作
            try {
                TimeUnit.SECONDS.sleep(3);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            boolean result=stampedReference.compareAndSet(100,2000,stamp,stamp+1);
            System.out.println(Thread.currentThread().getName()+"\t 修改成功否"+result+";最新版本号是:"+stampedReference.getStamp());
            System.out.println("最新的值是："+stampedReference.getReference());
        },"t4").start();
    }
}


